package com.jintian.smart.kernel.flowable.component;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import com.jintian.smart.kernel.common.util.StringUtil;
import com.jintian.smart.kernel.core.auth.IOperator;
import com.jintian.smart.kernel.core.auth.IOrgUnitQuery;
import com.jintian.smart.kernel.core.dto.OrgUnit;
import com.jintian.smart.kernel.flowable.api.PermissionService;
import com.jintian.smart.kernel.flowable.engine.DelegateProcessEngine;
import org.flowable.identitylink.api.IdentityLinkInfo;
import org.flowable.identitylink.api.IdentityLinkType;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


@Component
public class DefaultPermissionService extends DelegateProcessEngine implements PermissionService {
    @Autowired
    private IOrgUnitQuery query;

    /**
     * 所有者或受让人
     */
    @Override
    public boolean isTaskOwnerOrAssignee(IOperator operator, Task task) {
        return StringUtil.equalsAny(operator.getId(), task.getOwner(), task.getAssignee());
    }

    /**
     * 候选人
     */
    @Override
    public boolean isTaskCandidate(IOperator IOperator, Task task) {
        for (IdentityLinkInfo link : task.getIdentityLinks()) {
            if (IdentityLinkType.CANDIDATE.equals(link.getType())) {
                if (StringUtil.isNotBlank(link.getUserId())) {
                    if (link.getUserId().equals(IOperator.getId())) {
                        return true;
                    }
                } else if (StringUtil.isNotBlank(link.getGroupId())) {
                    String[] args = link.getGroupId().split(":");
                    String kind = null;
                    String code = null;
                    if (args.length == 1) {
                        kind = "role";
                        code = args[0];
                    } else {
                        kind = args[0];
                        code = args[1];
                    }
                    if (this.isMemberOfGroup(IOperator, kind, code)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * 参与者
     */
    @Override
    public boolean isTaskParticipant(IOperator IOperator, Task task) {
        for (IdentityLinkInfo link : task.getIdentityLinks()) {
            if (IdentityLinkType.PARTICIPANT.equals(link.getType())) {
                if (IOperator.getId().equals(link.getUserId())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 分组成员
     */
    @Override
    public boolean isMemberOfGroup(IOperator IOperator, String groupKind, String groupCode) {
        if ("role".equals(groupKind)) {
            return IOperator.hasRole(groupCode);
        } else if ("pos".equals(groupKind)) {
            return IOperator.hasPos(groupCode);
        } else if ("org".equals(groupKind)) {
            return IOperator.subordinateOrg(groupCode);
        }
        return false;

    }

    @Override
    public boolean canExecute(IOperator IOperator, Task task) {
        if (StringUtil.isAllBlank(task.getOwner(), task.getAssignee())) {
            if (task.getIdentityLinks().size() == 0) {
                return true;
            }
            return this.isTaskCandidate(IOperator, task);
        } else {
            return this.isTaskOwnerOrAssignee(IOperator, task);
        }
    }

    @Override
    public List<OrgUnit> getCanExecutor(Task task) {
        Set<OrgUnit> orgUnitList = new LinkedHashSet<>();
        if (StringUtil.isNotBlank(task.getAssignee())) {
            OrgUnit unit = query.query(OrgUnit.OrgKind.USER.name(), task.getOwner(), false);
            if (unit != null) {
                orgUnitList.add(unit);
                return new ArrayList<>(orgUnitList);
            }
        }
        if (StringUtil.isNotBlank(task.getOwner())) {
            OrgUnit unit = query.query(OrgUnit.OrgKind.USER.name(), task.getOwner(), false);
            if (unit != null) {
                orgUnitList.add(unit);
                return new ArrayList<>(orgUnitList);
            }
        }

        for (IdentityLinkInfo link : task.getIdentityLinks()) {
            if (IdentityLinkType.CANDIDATE.equals(link.getType())) {
                if (StringUtil.isNotBlank(link.getUserId())) {
                    OrgUnit unit = query.query(OrgUnit.OrgKind.USER.name(), task.getOwner(), false);
                    if (unit != null) {
                        orgUnitList.add(unit);
                    }
                } else if (StringUtil.isNotBlank(link.getGroupId())) {
                    String[] args = link.getGroupId().split(":");
                    String kind = null;
                    String code = null;
                    if (args.length == 1) {
                        kind = "role";
                        code = args[0];
                    } else {
                        kind = args[0];
                        code = args[1];
                    }
                    OrgUnit unit = query.query(kind, code, false);
                    if (unit != null) {
                        orgUnitList.add(unit);
                    }
                }
            }
        }
        return new ArrayList<>(orgUnitList);
    }
}
